òɾۿûѧϰʹá
ԭַhttps://www.joinquant.com/post/13706

ԭһ˵ʽ鵽ԭĺ߽ۡ


ԭĲԴ£

# 뺯
import jqdata
from jqlib.technical_analysis import *
import datetime
import pandas as pd
import numpy as np
# ʼ趨׼ȵ
def initialize(context):
    # 趨300Ϊ׼
    set_benchmark('000300.XSHG')
    # ̬Ȩģʽ(ʵ۸)
    set_option('use_real_price', True)
    # ݵ־ log.info()
    log.info('ʼʼȫֻһ')
    # ˵orderϵAPIıerror͵log
    log.set_level('order', 'error')
        #send_message('Ͳ')
    init_cash = 80000  # ʼʽ
    set_subportfolios([SubPortfolioConfig(cash=init_cash, type='stock')])

    # 趨300Ϊ׼
    set_benchmark('000300.XSHG')
    # ̬Ȩģʽ(ʵ۸)
    set_option('use_real_price', True)

    # ҪĹƱأg:globalΪȫֱ
    g.security = ['002241.XSHE', '000333.XSHE','002230.XSHE','002747.XSHE','002415.XSHE']
    g.holding_high_price = 0  # ڼ߼
    g.init_price = 0  # Ʊʼ۸,ڼƱ
    #for stk in g.security:
    # ȡƱ̼
    #  close_data = attribute_history(stk, 5, '1d', ['close'])
    # ȡһʱ۸
    #  g.init_price = close_data['close'][-1]
    #history(5, security_list=['000001.XSHE', '000002.XSHE'])
    close_data = history(5,unit='1d',field='close', security_list=g.security)
    #print(close_data)
    g.init_price = close_data.iloc[-1]
    #ȡóʼǰһйƱ̼۸
    #print(g.init_price)
    g.maxnum = 5  # ֲ
    g.lower = -2  # 
    g.upper = 1  # 
    g.zscore_window = 60  # zscore
    g.ma_window = 20  # ߴ
    ### Ʊ趨 ###
    # ƱÿʽʱǣʱӶ֮ʱӶ֮ǧ֮һӡ˰, ÿʽӶͿ5Ǯ
    set_order_cost(OrderCost(close_tax=0.001, open_commission=0.0003, close_commission=0.0003, min_commission=5),
                   type='stock')
    
    ## кreference_securityΪʱĲοģıֻ֣˴'000300.XSHG''510300.XSHG'һģ
      # ǰ
    run_daily(before_market_open, time='before_open', reference_security='000300.XSHG') 
      # ʱ
    run_daily(market_open, time='open', reference_security='000300.XSHG')
      # ̺
    run_daily(after_market_close, time='after_close', reference_security='000300.XSHG')

#źź
def get_buy_sell(context):
    buy, sell = [], []
    # ȡõǰõʽ
    cash = context.portfolio.available_cash
    # 趨ߴڳ
    n1 = 5 
    #5վ
    n2 = 10
    #10վ
    close_data = history(5,unit='1d',field='close', security_list=g.security)
    #ս
    for stk in g.security:
        # ȡһʱ۸
        previous_price = close_data.iloc[-1][stk]
        # һʱ۸
        record(stock_price=previous_price)
        # Ʊ
        stock_returns = (previous_price - g.init_price[stk]) / g.init_price[stk]
        # һʱֹ棬鿴Ŵ100
        record(stock_returns=stock_returns * 100)
        # ȡƱ̼
        close_data1 = attribute_history(stk, n2 + 2, '1d', ['close'], df=False)
        ma_n1 = close_data1['close'][-n1:].mean()
        # ȡùȥ ma_n2 ƽ۸
        ma_n2 = close_data1['close'][-n2:].mean()
        hold = context.subportfolios[0].long_positions <> {}
        #print('Ƿֲ֣')
        #print(hold)
        selladj = analysis_sell(context, stk) or ma_n1 < ma_n2
        #print('Ƿflag%s :' %(stk))
        #print(selladj)
        
        #жϸùǷ־λ
        if hold and selladj:
            #б־λ
            sell.append(stk)
            print("ж %s:%%" % (stk))
            send_message("ж %s:%%" % (stk))
    #жź        
    for stk in g.security:
        
        ma_n1 = close_data1['close'][-n1:].mean()
        # ȡùȥ ma_n2 ƽ۸
        ma_n2 = close_data1['close'][-n2:].mean()
        buyadj = analysis_buy(context, stk) and ma_n1 > ma_n2*0.95
        #print(analysis_buy(context, stk))
        #print(ma_n1 >= ma_n2)
        #print('Ƿflag%s :' %(stk))
        #print(buyadj)
        if buyadj:
            buy.append(stk)
            print("ж %s:%%" % (stk))
            send_message("ж %s:%%" % (stk))    
    return buy, sell































## ǰк     
def before_market_open(context):
    # ʱ
    log.info('ʱ(before_market_open)'+str(context.current_dt.time()))

    # ΢ŷϢģ⽻ף΢Ч
    print('õһ~')
    
    g.buy, g.sell = get_buy_sell(context)
    # ҪĹƱƽУg.Ϊȫֱ
    #g.security = '000001.XSHE'
    
## ʱк
def market_open(context):
    log.info('ʱ(market_open):'+str(context.current_dt.time()))
    #security = g.security
    # ȡƱ̼
    #close_data = attribute_history(security, 5, '1d', ['close'])
    # ȡùȥƽ۸
    #MA5 = close_data['close'].mean()
    # ȡһʱ۸
    #current_price = close_data['close'][-1]
    # ȡõǰֽ
    #cash = context.portfolio.available_cash
    # 
    for code in g.sell:
        order_target(code, 0)
    # 
    
    if len(g.buy)>0 and len(context.portfolio.positions)>0:
        for stock in context.portfolio.positions:
            holdsell = context.portfolio.positions[stock].closeable_amount
            print('ɽַɢֲ%s' %holdsell)
            if holdsell>100:
               order_target(stock, holdsell/2)
        
    cash_per_stock = context.portfolio.available_cash    
    if len(g.buy)>0:    
        cash_per_stock = context.portfolio.available_cash/len(g.buy) # ʽ
    for code in g.buy:
        hold = len(context.portfolio.positions)
        # δﵽֲ
        if hold < g.maxnum and cash_per_stock>8000 :
            order_target_value(code, cash_per_stock)
    print('buy: %d  sell: %d  hold: %d' % (len(g.buy), len(g.sell), len(context.portfolio.positions)))

    # һʱ۸߳ƽ1%, ȫ
    #if current_price > 1.01*MA5:
        # ¼
    #    log.info("۸ھ 1%%,  %s" % (security))
        #  cash Ʊ
    #    order_value(security, cash)
    # һʱ۸ƽ, ղ
    #elif current_price < MA5 and context.portfolio.positions[security].closeable_amount > 0:
        # ¼
    #    log.info("۸ھ,  %s" % (security))
        # йƱ,ʹֻƱճΪ0
    #    order_target(security, 0)
 
## ̺к  
def after_market_close(context):
    log.info(str('ʱ(after_market_close):'+str(context.current_dt.time())))
    #õгɽ¼
    trades = get_trades()
    for _trade in trades.values():
        log.info('ɽ¼'+str(_trade))
    log.info('һ')
    log.info('##############################################################')







#
def analysis_sell(context, security):
    # ĳ֧ƱǷʱ
    # MACD 
    # 𳬹15%
    # ڼ߼µ15%
    sellflag=False
    #ֵ0 ĬΪ ֵΪ1ùƱ
    # MACD 
    if isMACDDead(context, security):
        # йƱ,ʹֻƱճΪ0
        sellflag=True 
        # ¼
        msg_to_send = "Selling %s:macd_dead" % (security)
        log.info(msg_to_send)
        #send_message(msg_to_send, channel='weixin')

    # 𳬹15%
    price = context.subportfolios[0].long_positions[security].price
    avg_cost = context.subportfolios[0].long_positions[security].avg_cost

    if price <> 0 and price < avg_cost * 0.93:
        # йƱ,ʹֻƱճΪ0
        #order_target(security, 0)
        sellflag=True
        # ¼
        msg_to_send = "Selling %s:𳬹15%%" % (security)
        log.info(msg_to_send)
        #send_message(msg_to_send, channel='weixin')
    #ֵعZscore
    
    yesterday = context.current_dt - datetime.timedelta(1)  # 
    count = g.zscore_window + g.ma_window - 1  # 2
    code = security
    price_df = get_price(g.security, end_date=yesterday, fields='close', count=count).close
    #if d.has_key:
    #print(price_df)
    try:
        #print('zscoreϵ0')
        single_df = price_df[code].to_frame('close')
        #print('zscoreϵ1')
        single_df['ma'] = pd.rolling_mean(single_df.close, window=g.ma_window)  # 
        #print('zscoreϵ2')
        single_df.dropna(inplace=True)
        single_df['sub'] = single_df.close - single_df.ma  # Բֵлع
        zscore_mean = single_df['sub'].mean(); zscore_std = single_df['sub'].std()  # ֵͱ׼
        zscore_value = (single_df['sub'][-1] - zscore_mean) / zscore_std
        #print('zscoreϵ3')
        if zscore_value >= g.upper and price <> 0:  # 
            #order_target(security, 0)# zscoreֵ
            msg_to_send = "zscoreֵ %s:%%" % (security)
            print('zscoreֵ')
            log.info(msg_to_send)
            sellflag=True
    except:
        pass
    # ڼ߼µ15%
    # ȼڼ߼holding_high_price
    if price == 0:
        g.holding_high_price = 0  # ޳ֲ
    elif price > g.holding_high_price:
        g.holding_high_price = price  # ùɼΪֵ

        if price < g.holding_high_price * 0.93:
            # йƱ,ʹֻƱճΪ0
            #order_target(security, 0)
            # ¼
            msg_to_send = "Selling %s:ڼ߼µ15%%" % (security)
            log.info(msg_to_send)
            sellflag=True
            #send_message(msg_to_send, channel='weixin')
    return sellflag
    # ӦδɽҪ
    pass


def analysis_buy(context, security):
    # ĳ֧ƱǷʱ
    # MACD 
    buyflag=False
    #ֵ0 ĬΪ ֵΪ1ùƱ
    # ȡõǰõʽ
    #cash = context.portfolio.available_cash

    # MACD 
    if isMACDGold(context, security):
        buyflag=True
    #  cash Ʊ
    #    if cash > 60000:
    #        dividecash=cash/5*4
    #    else: dividecash=cash
    #    dividecash=cash    
    #    order_value(security, dividecash)
    # ¼
        msg_to_send = "Buying %s:macd_gold" % (security)
        log.info(msg_to_send)
        #send_message(msg_to_send, channel='weixin')
    return buyflag
















def isMACDGold(context, security):
    '''
    жǷ MACD 
    return True or False
    '''
    # ǰһյ
    check_date = context.current_dt.strftime('%Y-%m-%d')
    previous_date = context.previous_date

    # 㲢 security  MACD ֵ
    macd_dif, macd_dea, macd_macd = MACD(security, check_date=check_date, SHORT=12, LONG=26, MID=9)
    previous_date_macd_dif, previous_date_macd_dea, previous_date_macd_macd = MACD(security, check_date=previous_date,
                                                                                   SHORT=12, LONG=26, MID=9)

    if previous_date_macd_macd[security] < 0 and macd_macd[security] > 0:
        return True
    else:
        return False


def isMACDDead(context, security):
    '''
    жǷ MACD 
    return True or False
    '''
    # ǰһյ
    check_date = context.current_dt.strftime('%Y-%m-%d')
    previous_date = context.previous_date

    # 㲢 security  MACD ֵ
    macd_dif, macd_dea, macd_macd = MACD(security, check_date=check_date, SHORT=12, LONG=26, MID=9)
    previous_date_macd_dif, previous_date_macd_dea, previous_date_macd_macd = MACD(security, check_date=previous_date,
                                                                                   SHORT=12, LONG=26, MID=9)

    if previous_date_macd_macd[security] > 0 and macd_macd[security] < 0:
        return True
    else:
        return False
